package com.zzyl.nursing.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.core.page.PageDomain;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.DeviceDataMapDto;
import com.zzyl.nursing.dto.DeviceDto;
import com.zzyl.nursing.dto.UserAddRequestDto;
import com.zzyl.nursing.service.IDeviceService;
import com.zzyl.nursing.service.IElderService;
import com.zzyl.nursing.vo.MemberElderVo;
import com.zzyl.nursing.vo.member.DeviceDataMapVo;
import com.zzyl.nursing.vo.member.HealthDataVo;
import com.zzyl.nursing.vo.member.PropertyStatusInfoVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.FamilyMemberElderMapper;
import com.zzyl.nursing.service.IFamilyMemberElderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * 客户老人关联Service业务层处理
 *
 * @author ruoyi
 * @date 2024-09-28
 */
@Service
public class FamilyMemberElderServiceImpl extends ServiceImpl<FamilyMemberElderMapper,FamilyMemberElder> implements IFamilyMemberElderService
{
    @Autowired
    private FamilyMemberElderMapper familyMemberElderMapper;

    @Autowired
    private IElderService elderService;

    @Autowired
    RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
    @Autowired
    private DeviceDataServiceImpl deviceDataServiceImpl;

    /**
     * 查询客户老人关联
     *
     * @param id 客户老人关联主键
     * @return 客户老人关联
     */
    @Override
    public FamilyMemberElder selectFamilyMemberElderById(Long id)
    {
        return getById(id);
    }

    /**
     * 查询客户老人关联列表
     *
     * @param familyMemberElder 客户老人关联
     * @return 客户老人关联
     */
    @Override
    public List<FamilyMemberElder> selectFamilyMemberElderList(FamilyMemberElder familyMemberElder)
    {
        return familyMemberElderMapper.selectFamilyMemberElderList(familyMemberElder);
    }

    /**
     * 新增客户老人关联
     *
     * @param familyMemberElder 客户老人关联
     * @return 结果
     */
    @Override
    public int insertFamilyMemberElder(FamilyMemberElder familyMemberElder)
    {
        return save(familyMemberElder)?1:0;
    }

    /**
     * 修改客户老人关联
     *
     * @param familyMemberElder 客户老人关联
     * @return 结果
     */
    @Override
    public int updateFamilyMemberElder(FamilyMemberElder familyMemberElder)
    {
        return updateById(familyMemberElder)?1:0;
    }

    /**
     * 批量删除客户老人关联
     *
     * @param ids 需要删除的客户老人关联主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberElderByIds(Long[] ids)
    {
        return removeByIds(Arrays.asList(ids))?1:0;
    }

    /**
     * 删除客户老人关联信息
     *
     * @param id 客户老人关联主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberElderById(Long id)
    {
        return removeById(id)?1:0;
    }

    /**
     * 绑定老人
     * @param dto
     */
    @Override
    public void add(UserAddRequestDto dto) {
        //根据身份证查询老人,判断老人是否存在
        LambdaQueryWrapper<Elder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Elder::getIdCardNo, dto.getIdCard());
        Elder elder = elderService.getOne(queryWrapper);

        if (ObjectUtil.isEmpty(elder)) {
            throw new RuntimeException("老人不存在");
        }

        //获取用户Id
        Long userId = UserThreadLocal.getUserId();

        //判断老人是否已被绑定
        LambdaQueryWrapper<FamilyMemberElder> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(FamilyMemberElder::getElderId, elder.getId());
        queryWrapper2.eq(FamilyMemberElder::getFamilyMemberId,userId);
        FamilyMemberElder familyMemberElder = getOne(queryWrapper2);

        if (ObjectUtil.isNotEmpty(familyMemberElder)) {
            throw new RuntimeException("老人已被绑定");
        }

        //封装绑定信息
        familyMemberElder = FamilyMemberElder.builder()
                                             .familyMemberId(userId)
                                             .elderId(elder.getId())
                                             .remark(dto.getRemark())
                                             .build();

        //新增绑定数据
        save(familyMemberElder);

    }

    /**
     * 查询家人列表详细信息
     * @param pageDomain
     * @return
     */
    @Override
    public List<MemberElderVo> queryFamilies(PageDomain pageDomain) {
        //获取用户Id
        Long userId = UserThreadLocal.getUserId();

        //联表查询老人集合
        List<MemberElderVo> memberElderVos = familyMemberElderMapper.queryFamilies(userId);

        memberElderVos.forEach(item -> {
            item.setMid(item.getFamilyMemberId());
            item.setName(item.getElderName());
        });
        return memberElderVos;
    }

    @Autowired
    private IDeviceService deviceService;

    /**
     * 查询家人健康数据
     * @param dto
     * @return
     */
    @Override
    public Map<String, PropertyStatusInfoVo> QueryDevicePropertyStatus(DeviceDto dto) {
        //获取iotId
        Device device = deviceService.getOne(Wrappers.<Device>lambdaQuery(Device.class)
                .eq(Device::getProductKey, dto.getProductKey())
                .eq(Device::getDeviceName, dto.getDeviceName()));

        //判断老人是否绑定了设备
        if(ObjectUtil.isEmpty(device)) {
            throw new RuntimeException("老人未绑定设备");
        }

        String iotId = device.getIotId();

        //从redis获取设备数据
        String jsonStr = (String) redisTemplate.opsForHash().get(CacheConstants.IOT_DEVICE_LAST_DATA, iotId);

        //判断是否获取到了数据
        if(ObjectUtil.isEmpty(jsonStr)) {
            throw new RuntimeException("系统中未查询到数据,请联系管理员");
        }

        //转换为JSONObject
        List<DeviceData> deviceProperty = JSONUtil.toList(jsonStr, DeviceData.class);

        //封装数据
        List<HealthDataVo> list = new ArrayList<>();
        deviceProperty.forEach(item -> {
            HealthDataVo healthDataVo = HealthDataVo.builder()
                    .identifier(item.getFunctionId())
                    .value(item.getDataValue())
                    .time(LocalDateTimeUtil.toEpochMilli(item.getAlarmTime()))
                    .dataType(getDataTypeByIdentifier(item.getFunctionId()))
                    .name(getNameByIdentifier(item.getFunctionId()))
                    .unit(getUnitByIdentifier(item.getFunctionId()))
                    .build();
            list.add(healthDataVo);
        });

        Map<String, PropertyStatusInfoVo> propertyMap = new HashMap<>();
        propertyMap.put("list",new PropertyStatusInfoVo(list));

        return propertyMap;
    }

    /**
     * 1.5  按天统计查询指标数据
     * @param dto
     * @return
     */
    @Override
    public List<Map<String, Object>> queryDeviceDataListByDay(DeviceDataMapDto dto) {
        LocalDateTime startTime = LocalDateTimeUtil.of(Long.parseLong(dto.getStartTime()));
        LocalDateTime endTime = LocalDateTimeUtil.of(Long.parseLong(dto.getEndTime()));
        List<DeviceDataMapVo> originalList = familyMemberElderMapper.queryDeviceDataListByDay(dto.getIotId(), dto.getFunctionId(), startTime, endTime);


        List<Map<String, Object>> list = originalList.stream()
                .map(vo -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("dateTime", vo.getDateTime());
                    map.put("dataValue", Double.valueOf(vo.getDataValue()));
                    return map;
                })
                .collect(Collectors.toList());

        // 遍历从00:00到23:00的每一个小时
        for (int hour = 0; hour <= 23; hour++) {
            String hourStr = String.format("%02d:00", hour); // 格式化小时为两位数

            // 检查是否已存在该小时段
            boolean exists = list.stream()
                    .anyMatch(map -> hourStr.equals(map.get("dateTime")));

            // 如果不存在，则插入键值对，值为0.0
            if (!exists) {
                Map<String, Object> newEntry = new HashMap<>();
                newEntry.put("dateTime", hourStr);
                newEntry.put("dataValue", 0.0);
                list.add(newEntry);
            }
        }

        // 对结果进行排序
        list.sort((a, b) -> ((String) a.get("dateTime")).compareTo((String) b.get("dateTime")));

        return list;
    }

    /**
     * 1.6  按周统计查询指标数据
     * @param dto
     * @return
     */
    @Override
    public List<Map<String, Object>> queryDeviceDataListByWeek(DeviceDataMapDto dto) {
        LocalDateTime startTime = LocalDateTimeUtil.of(Long.parseLong(dto.getStartTime()));
        LocalDateTime endTime = LocalDateTimeUtil.of(Long.parseLong(dto.getEndTime()));
        List<DeviceDataMapVo> originalList = familyMemberElderMapper.queryDeviceDataListByWeek(dto.getIotId(), dto.getFunctionId(), startTime, endTime);

        //将集合内元素转换为Map
        List<Map<String, Object>> list = originalList.stream()
                .map(vo -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("dateTime", vo.getDateTime());
                    map.put("dataValue", Double.valueOf(vo.getDataValue()));
                    return map;
                })
                .collect(Collectors.toList());

        //提取日期
        LocalDate startDate = startTime.toLocalDate();

        //设置日期格式
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM.dd");
        LocalDate date;

        // 遍历起始日期开始7天
        for (int day = 0; day < 7; day++) {
            date = startDate.plusDays(day);
            String dateStr = date.format(dateFormatter);

            // 检查是否已存在该天
            boolean exists = list.stream()
                    .anyMatch(map -> dateStr.equals(map.get("dateTime")));

            // 如果不存在，则插入键值对，值为0
            if (!exists) {
                Map<String, Object> newEntry = new HashMap<>();
                newEntry.put("dateTime", dateStr);
                newEntry.put("dataValue", 0);
                list.add(newEntry);
            }
        }

        // 对结果进行排序
        list.sort((a, b) -> ((String) a.get("dateTime")).compareTo((String) b.get("dateTime")));

        return list;
    }

    private String getDataTypeByIdentifier(String functionId) {
        switch (functionId) {
            case "BodyTemp":
                return "float";
            case "HeartRate":
                return "int";
            case "xueyang":
                return "int";
            case "BatteryPercentage":
                return "double";
        }
        return null;
    }

    private String getNameByIdentifier(String functionId) {
        switch (functionId) {
            case "BodyTemp":
                return "体温";
            case "HeartRate":
                return "心率";
            case "xueyang":
                return "血氧";
            case "BatteryPercentage":
                return "电池电量百分比";
        }
        return null;
    }

    private String getUnitByIdentifier(String functionId) {
        switch (functionId) {
            case "BodyTemp":
                return "℃";
            case "HeartRate":
                return "";
            case "xueyang":
                return null;
            case "BatteryPercentage":
                return "%";
        }
        return null;
    }

}
